#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <pthread.h>
#include <sqlite3.h>
#include "command_parser.h"
#include "list.h"
#define PORT 10086
#define BUFFER_SIZE 1024

// #define Password "666666"
// #define username "666666"
ListNode *head = NULL;
sqlite3 *db;
void init_db() {
    if (sqlite3_open("chat_server.db", &db) != SQLITE_OK) {
        fprintf(stderr, "Database error: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }

    // 创建用户表
    const char *create_users_table = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT, password TEXT, status INTEGER);";
    if (sqlite3_exec(db, create_users_table, NULL, NULL, NULL) != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }

    // 创建在线用户表
    const char *create_online_users_table = "CREATE TABLE IF NOT EXISTS online_users (user_id INTEGER PRIMARY KEY, connect_fd INTEGER);";
    if (sqlite3_exec(db, create_online_users_table, NULL, NULL, NULL) != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }
  
    const char *insert_user_sql = "INSERT INTO users (username, password, status) VALUES ('666666', '654321', 0);";
    if (sqlite3_exec(db, insert_user_sql, NULL, NULL, NULL) != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }
}


void *thread_function(void *arg) {
    int attempts = 0; // 记录登陆次数
    const int MAX_ATTEMPTS = 3; // 最大登录尝试次数
    char buffer[BUFFER_SIZE] = {0}; // 用于存储从客户端接收的数据和发送的数据。
    int my_connect_socket; // 客户端连接的套接字描述符。
    my_connect_socket = *((int *)arg);
    int UserID = 0;
    char username[16] = {0};
    char Password[16] = {0};
     char bb[16] = {0}; // 临时缓冲区，存储从客户端接收的数据。
    sqlite3_stmt *stmt; // 声明 stmt 变量

    // 向客户端发送消息, 要求客户端输入用户名
    strcpy(buffer, "Please enter your username: "); // 向客户端发送消息, 要求客户端输入用户名
    send(my_connect_socket, buffer, strlen(buffer), 0); // 发送消息
    read(my_connect_socket, buffer, BUFFER_SIZE); // 接收数据
    strcpy(username, buffer); // 将字符串复制到 username

    // 向客户端发送消息, 要求客户端输入密码
    strcpy(buffer, "Please enter your password: "); // 向客户端发送消息, 要求客户端输入密码
    send(my_connect_socket, buffer, strlen(buffer), 0); // 发送消息

    // 进行密码验证
    while (attempts < MAX_ATTEMPTS) { // 循环尝试登录
        // 接收数据前，清空缓冲区
        memset(buffer, 0, BUFFER_SIZE);
        // 假设从客户端接收密码

        if (recv(my_connect_socket, buffer, sizeof(buffer), 0) > 0) { // 接收数据
            strcpy(Password, buffer); // 将字符串复制到 Password

            // 查询数据库验证用户名和密码
            const char *sql = "SELECT id FROM users WHERE username = 666666 AND password = 654321 AND status = 0;";
            if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) { // 编译SQL语句
                fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); // 打印错误信息
                close(my_connect_socket);
                pthread_exit(NULL);
            }

            sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);// 绑定参数
            sqlite3_bind_text(stmt, 2, Password, -1, SQLITE_STATIC);// 绑定参数

            if (sqlite3_step(stmt) == SQLITE_ROW) // 执行SQL语句
            {
                UserID = sqlite3_column_int(stmt, 0);
                snprintf(buffer, sizeof(buffer), "Login successful!!\n");
                send(my_connect_socket, buffer, strlen(buffer), 0);

                // 更新用户状态为在线
                const char *update_sql = "UPDATE users SET status = 1 WHERE id = ?;";
                sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL);
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                // 将用户ID和套接字描述符添加到在线用户表
                const char *insert_online_sql = "INSERT INTO online_users (user_id, connect_fd) VALUES (?, ?);";
                sqlite3_prepare_v2(db, insert_online_sql, -1, &stmt, NULL);
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_bind_int(stmt, 2, my_connect_socket);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                break;
            } else {
                snprintf(buffer, sizeof(buffer), "Login failed! Attempt %d of %d\n", attempts + 1, MAX_ATTEMPTS);
                send(my_connect_socket, buffer, strlen(buffer), 0);
                attempts++;
            }

            sqlite3_finalize(stmt);
        }
    }

    // 不能再登录（次数达上限）
    if (attempts == MAX_ATTEMPTS) {
        // 关闭连接
        close(my_connect_socket);
        pthread_exit(NULL);
    }

    // 登录成功后的处理逻辑...

    // 登录成功后，将用户ID和套接字描述符添加到链表中
    List *ll = NULL; // 定义 list 变量
    append(ll, 0, UserID, my_connect_socket); // 添加用户
    // 初始化
    char *command = NULL; // 命令
    char *param = NULL; // 参数
    ListNode *temp; // 链表节点指针
    int loop = 1;

    int sid = 0; // 目标用户ID
    int dia_socket = 0; // 目标套接字
    int dia_loop = 0; // 循环标志

    while (loop) {
        memset(buffer, 0, BUFFER_SIZE);
        // 读取客户端发送的消息
        read(my_connect_socket, buffer, BUFFER_SIZE);
        printf("Received message: %s\n", buffer);
        // 解析命令
        if (register_command(buffer, &command, &param) == 0) {
            printf("命令: %s\n", command);
            printf("参数: %s\n", param);
        } else {
            printf("解析命令失败\n");
        }

        if (strcmp(command, "cmd") == 0) { // 登录
            if (strcmp(param, "online_user") == 0) { // 获取在线用户
                // 用户信息的组装
                // 将链表中的所有用户ID拼接成一个字符串
                memset(buffer, 0, sizeof(buffer)); // 清空缓冲区
                memset(bb, 0, sizeof(bb)); //
                temp = head;

                while (temp != NULL) {
                    sprintf(bb, "%d", temp->UserID); // 拼接字符串
                    strcat(buffer, bb); //
                    temp = temp->next; // 下一个节点
                }
                strcat(buffer, "\n"); //
                send(my_connect_socket, buffer, strlen(buffer), 0); // 发送数据
                // 向客户端发送响应
                printf("all user ID query succeeded!\n"); // 打印日志
            }

            if (strcmp(param, "exit") == 0) { // exit
                // 退出时，删除用户节点
                delete_node(&head, UserID);

                // 更新用户状态为离线
                const char *update_sql = "UPDATE users SET status = 0 WHERE id = ?;";
                sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL);
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                // 从在线用户表中删除用户
                const char *delete_online_sql = "DELETE FROM online_users WHERE user_id = ?;";
                sqlite3_prepare_v2(db, delete_online_sql, -1, &stmt, NULL);
                sqlite3_bind_int(stmt, 1, UserID);
                sqlite3_step(stmt);
                sqlite3_finalize(stmt);

                loop = 0;
            }
        }

        // 群发
        if (strcmp(command, "all") == 0) { // 群发
            memset(buffer, 0, sizeof(buffer));
            memset(bb, 0, sizeof(bb));
            temp = head;
            // 群聊数据的组装
            sprintf(bb, "%d->", UserID); // 群聊数据
            strcat(buffer, bb);
            strcat(buffer, param);

            while (temp != NULL) {
                send(temp->Connect_fd, buffer, strlen(buffer), 0);
                temp = temp->next;
            }
        }

        // 私聊
        if (strcmp(command, "usr") == 0) { // 私聊
            sid = atoi(param);
            printf("sid: %d\n", sid);
            temp = head;

            while (temp != NULL) {
                if (temp->UserID == sid) { // 找到目标用户
                    dia_socket = temp->Connect_fd; // 找到目标用户连接套接字
                    printf("dia socket: %d\n", dia_socket); // 输出目标用户套接字
                    dia_loop = 1;
                }
                temp = temp->next;
            }

            if (dia_socket == 0) { // 目标用户不存在
                send(my_connect_socket, "user not find!\n", strlen(buffer), 0); // 发送消息
            }

            while (dia_loop) {
                memset(buffer, 0, BUFFER_SIZE);
                read(my_connect_socket, buffer, BUFFER_SIZE);
                if (strncmp(buffer, "quit", 4) == 0) {
                    memset(buffer, 0, BUFFER_SIZE);
                    strcat(buffer, "DIALOG OVER!");
                    send(my_connect_socket, buffer, strlen(buffer), 0);
                    dia_loop = 0;
                }
                send(dia_socket, buffer, strlen(buffer), 0);
            }
        }

        // 增加 private
        if (strcmp(command, "private") == 0) {
            // 私聊命令处理
            char *target_id_str = strtok(param, " ");
            char *message = strtok(NULL, "");
            if (target_id_str && message) {
                int target_id = atoi(target_id_str);
                temp = head;
                while (temp != NULL) {
                    if (temp->UserID == target_id) {
                        send(temp->Connect_fd, message, strlen(message), 0);
                        break;
                    }
                    temp = temp->next;
                }
                if (temp == NULL) {
                    send(my_connect_socket, "Target user not found!\n", strlen(buffer), 0);
                }
            } else {
                send(my_connect_socket, "Invalid private message format!\n", strlen(buffer), 0);
            }
        }

        // 广播
        if (strcmp(command, "broadcast") == 0) {
            // 广播命令处理
            temp = head;
            while (temp != NULL) {
                if (temp->Connect_fd != my_connect_socket) { // 不发送给自己
                    send(temp->Connect_fd, param, strlen(param), 0);
                }
                temp = temp->next;
            }
        }

        // 释放动态分配的内存
        free(command);
        free(param);
        if (loop == 0)
            break;
    }

    close(my_connect_socket); // 关闭连接
    pthread_exit(NULL);
}
   

int main()
{
  
  init_db();

int server_fd, my_connect_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
//创建 socket 文件描述符

if((server_fd= socket(AF_INET,SOCK_STREAM,0))==0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置地址重用选项
int opt = 1;
if (setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR, &opt, sizeof(opt)) < 0)
{
perror("setsockopt");
close(server_fd);
exit(EXIT_FAILURE);
}
//绑定 socket 到本地地址
address.sin_family = AF_INET;
address.sin_addr.s_addr =INADDR_ANY;
address.sin_port = htons(PORT);

if(bind(server_fd,(struct sockaddr *)&address,addrlen)< 0)
{
perror("bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// 监听连接请求
if (listen(server_fd, 3)< 0)
{
perror("listen");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);
pthread_t thread_id;
// 设置线程属性为分离状态
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//线程分离
while (1)
{
// 接受一个新连接
if ((my_connect_socket = accept(server_fd,(struct sockaddr *)&address, (socklen_t*)&addrlen))< 0)
{
    perror("accept");
close(server_fd);
exit(EXIT_FAILURE);
}
if (pthread_create(&thread_id, &attr, thread_function, (void *)&my_connect_socket) !=0)

{
perror("创建线程1失败");
exit(EXIT_FAILURE);
}
}
// 销毁线程属性
pthread_attr_destroy(&attr);
// 关闭监听套接字 
close(server_fd);
sqlite3_close(db);
return 0;
}

